home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DDJMAG
/
DDJ9212.ZIP
/
sound.asc
< prev
next >
Wrap
Text File
|
1992-11-30
|
11KB
|
279 lines
_SOUND AS A DATA TYPE_
by Aaron E. Walsh
[LISTING ONE]
/************************************************************************/
/* AddSoundTrackToMovie.c -- QuickTime program demonstrating how to add */
/* a sound track to a movie using data found in an snd sound resource. */
/* by Aaron E. Walsh Developed using Symantec Think C 5.0 and */
/* Apple QuickTime headers */
/************************************************************************/
#include <Types.h>
#include <Dialogs.h>
#include <Sound.h>
#include <Movies.h>
#include <MoviesFormat.h>
#define defaultChunkSize 32768
void main(void);
OSErr InitMacManagers(void);
void doSoundToMovie(void);
OSErr OpenSndFile(short vRef, Str255 fileName, short *rRef,
Handle *soundHandle);
void ConvertSndToMovie(short destVolume, Str255 destName, Handle sndH,
long chunkSize, Boolean CreateFile);
OSErr CreateSndDescriptor(Handle sndHandle, SoundDescriptionPtr sndDescriptP,
unsigned long *dataOffset,unsigned long *frameCount);
/***** main() -- simple main event loop ******/
void main()
{
OSErr error;
error = InitMacManagers();
if (!error)
{
doSoundToMovie(); /* focus of this article */
ExitMovies(); /* exit Movie Toolbox when done */
}
} /*main*/
/***** InitMacManagers() -- Initialize Toolbox Managers used here app. *****/
OSErr InitMacManagers()
{
OSErr error;
InitGraf(&qd.thePort);
FlushEvents(everyEvent,0);
InitWindows();
InitDialogs(nil);
InitCursor();
MaxApplZone();
/* attempt to initialize the Movie Toolbox: a better approach */
/* would be to use the Gestalt Manager, as detailed in my */
/* July 1992 DDJ article "Programming QuickTime" */
error = EnterMovies();
return (error);
} /*InitMacManagers*/
/**** doSoundToMovie() -- simple interface: select sound file & add it as a */
/* QT sound track ****/
void doSoundToMovie()
{
Point where;
SFReply userReply;
Handle soundResourceHandle = nil;
short resourceRefNum = 0;
OSErr soundFileSelectErr, movieFileSelectErr;
SFTypeList movieFileTypes;
soundFileSelectErr=movieFileSelectErr = 1; /* initialize error flags */
/* select sound file: */
SFGetFile(where, "\p", nil, -1, nil, nil, &userReply);
if (userReply.good)
soundFileSelectErr = OpenSndFile (userReply.vRefNum,
userReply.fName,
&resourceRefNum,
&soundResourceHandle
);
/* select movie file: */
movieFileTypes[0] = 'MooV';
SFGetFile(where, "\p", nil, 1, movieFileTypes, nil, &userReply);
movieFileSelectErr = !userReply.good;
if (!soundFileSelectErr && !movieFileSelectErr)
ConvertSndToMovie(userReply.vRefNum, userReply.fName,
soundResourceHandle, defaultChunkSize, false);
else
SysBeep(1); /* beep to indicate conversion wasn't done */
} /*doSoundToMovie()*/
/** OpenSndFile() -- open given file and retrieve first snd resource found **/
OSErr OpenSndFile(short volRefNum, Str255 fileName, short *refNum,
Handle *soundHand)
{
FSSpec fileSpec;
OSErr error;
short saveResFile;
/* create file specification record: */
error = FSMakeFSSpec(volRefNum, 0, fileName, &fileSpec);
if (error) DebugStr("\pFSMakeFSSpec Failed");
if (*refNum)
{
CloseResFile(*refNum); /* close file once spec is created */
if (error = ResError()) DebugStr("\pCloseResFile Failed");
*refNum = 0;
}
*refNum = FSpOpenResFile(&fileSpec, fsRdPerm); /* open using spec */
if (*refNum < 0) DebugStr("\pFSpOpenResFile Failed");
saveResFile = CurResFile(); /* save current resource refnum */
UseResFile(*refNum); /* switch to our newly opened file */
if (error = ResError()) DebugStr("\pUseResFile Failed");
*soundHand = Get1IndResource('snd ', 1); /* get first snd resource */
error = ResError();
UseResFile(saveResFile);
if (!*soundHand)
error = -1; /* return error if sound handle is nil */
return (error);
} /*OpenSndFile*/
/* ConvertSndToMovie()--create new movie sound track from snd resource data */
void ConvertSndToMovie(short destVolume, Str255 destName, Handle soundHand,
long chunkSize, Boolean CreateFile)
{
FSSpec destSpec;
short resID = 1;
short resRefNum;
OSErr theErr;
Track sndTrack = 0;
Media sndMedia = 0;
Movie theMovie;
unsigned long sndSize, bytes, dataOffset, numSampleFrames;
unsigned long totalSamples, chunkSamples, samples;
unsigned long bytesPerFrame, samplesPerFrame;
SoundDescription **descH;
SoundDescription *sndDescP;
descH = (SoundDescription **) NewHandleClear( sizeof(SoundDescription));
if (!descH) DebugStr("\pCould not get description handle");
sndDescP = *descH;
CreateSndDescriptor(soundHand, sndDescP, &dataOffset, &numSampleFrames);
bytesPerFrame = 1;
samplesPerFrame = 1;
theErr = FSMakeFSSpec(destVolume, 0, destName, &destSpec);
if (theErr == fnfErr) theErr = 0;
if (theErr) DebugStr("\pFSMakeFSSpec Failed");
theErr = OpenMovieFile(&destSpec, &resRefNum, fsRdWrPerm); // ALTERED!
if (theErr) DebugStr("\pOpenMovieFile Failed");
resID = 0;
theErr = NewMovieFromFile(&theMovie,resRefNum,&resID,destName,0,0L );
if (theErr) DebugStr("\pNewMovieFromFile Failed");
/* Now put it into a track */
sndTrack = NewMovieTrack(theMovie, 0, 0, 255);
if (theErr = GetMoviesError()) DebugStr("\pNewMovieTrack Failed");
sndMedia = NewTrackMedia(sndTrack, SoundMediaType,
((unsigned long)(*descH)->sampleRate) >> 16, nil, 0);
sndSize = GetHandleSize(soundHand) - dataOffset;
bytes = numSampleFrames * bytesPerFrame; /* number of bytes
we expect in file */
if (bytes > sndSize) /* sample too large */
{
SysBeep(1); /* give a beep to indication error occured */
numSampleFrames = sndSize / bytesPerFrame;
}
totalSamples = numSampleFrames * samplesPerFrame; /* samples in file */
if (!chunkSize)
chunkSamples = totalSamples; /* all in one chunk */
else
chunkSamples = (chunkSize * samplesPerFrame) / bytesPerFrame;
/* get size of chunk in samples */
theErr = BeginMediaEdits( sndMedia );
if (theErr) DebugStr("\pBeginMediaEdits Failed");
while (totalSamples)
{
samples = totalSamples; /* samples in chunk */
if (samples > chunkSamples)
samples = chunkSamples;
bytes = (samples * bytesPerFrame) / samplesPerFrame;
/* bytes in chunk */
theErr = AddMediaSample( sndMedia, soundHand, dataOffset,
bytes, (TimeValue) 1, (SampleDescriptionHandle)
descH, samples, 0, 0);
if (theErr) DebugStr("\pAddMediaSample Failed");
dataOffset += bytes;
totalSamples -= samples;
}
theErr = EndMediaEdits( sndMedia );
if (theErr) DebugStr("\pEndMediaEdits Failed");
theErr = InsertMediaIntoTrack(sndTrack,0L,0L,
GetMediaDuration(sndMedia), 0x10000);
if (theErr) DebugStr("\pInsertMediaIntoTrack Failed");
/* Write out the movie */
DisposHandle((Handle) descH);
if (CreateFile)
{
theErr = AddMovieResource( theMovie, resRefNum, &resID, destName );
if (theErr) DebugStr("\pAddMovieResource Failed");
}
else
{
theErr = UpdateMovieResource( theMovie, resRefNum, resID, destName );
if (theErr) DebugStr("\pUpdateMovieResource Failed");
}
theErr = CloseMovieFile( resRefNum);
if (theErr) DebugStr("\pCloseMovieFile Failed");
DisposeMovie(theMovie);
}/*ConvertSndToMovie*/
/**** CreateSndDescriptor() -- create a Sound Descriptor record from */
/* snd resource data ****/
OSErr CreateSndDescriptor(Handle sndHandle, SoundDescriptionPtr sndDescriptP,
unsigned long *dataOffset,unsigned long *frameCount)
{
short *i, synthCount, sndCommandCount;
SndCommand *SoundCommand;
SoundHeaderPtr sndHeadPtr;
HLock (sndHandle);
i = (short *) *sndHandle; /* get first word of snd resource */
if (*i != 1) /* deal only with format 1 snd resource */
return (-1); /* return error (-1) for other snd types */
i++;
synthCount = *i; /* count of modifiers/synthesizers in resource */
i++;
i += (synthCount * (1 + 2)); /* jump over modifiers/synthesizers, */
/* so we can get at the sound commands */
sndCommandCount = *i; /* count of sound commands in resource */
i++;
SoundCommand = (SndCommand*) i; /* get reference to 1st sound command */
sndDescriptP->descSize = sizeof(SoundDescription);
/*size of SoundDescription*/
sndDescriptP->resvd1 = 0; /* reserved by Apple */
sndDescriptP->resvd2 = 0; /* reserved by Apple */
sndDescriptP->version = 0; /* data version */
sndDescriptP->revlevel = 0; /* codec version */
sndDescriptP->vendor = 0; /* codec vendor */
sndDescriptP->compressionID = 0; /* sound compression 0=none*/
sndDescriptP->packetSize = 0; /* compression packet size,*/
/* 0 if not compressed */
sndDescriptP->numChannels = 1; /* number of channels of sound*/
sndDescriptP->sampleSize = 8; /* number of bits per sample */
sndDescriptP->dataFormat = 'raw '; /* uncompressed */
/* coerce in order to access sample rate, frame count, & data offsets*/
sndHeadPtr = (SoundHeaderPtr) (*sndHandle + SoundCommand->param2);
sndDescriptP->sampleRate = sndHeadPtr->sampleRate;
/*sample rate of data*/
*frameCount = sndHeadPtr->length; /* number of frames */
*dataOffset = sndHeadPtr->sampleArea - *sndHandle; /* offset to data */
HUnlock(sndHandle);
} /*CreateSndDescriptor*/